package ai.hou.camera.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import androidx.core.content.ContextCompat;

import java.io.ByteArrayOutputStream;
import java.io.File;

import ai.hou.camera.R;
import ai.hou.camera.util.BitmapUtils;
import ai.hou.camera.util.FileUtils;

/**
 * 用于裁剪的view
 *
 * @author zhaoxiaolei
 * @date 2021/3/15 11:10
 */
public class MagicCropView extends View {
    public static final int CORNER_LEFT_TOP = 1;
    public static final int CORNER_RIGHT_TOP = 2;
    public static final int CORNER_LEFT_BOTTOM = 3;
    public static final int CORNER_RIGHT_BOTTOM = 4;

    /**
     * 被裁减的bitmap
     */
    private Bitmap mCropBitmap;
    private Matrix mMatrix;
    private final Drawable mDragDrawable;
    private final Paint mPaint;
    private Rect mCropBounds;
    private Rect mBounds1;
    private Rect mBounds2;
    private Rect mBounds3;
    private Rect mBounds4;

    /**
     * 是否可以拖动
     */
    private boolean isDragView;
    /**
     * 是否允许拖动
     */
    private boolean dragCropEnable;
    /**
     * 拖动的是哪个角，1：左上，2：右上，3：左下，4：右下
     */
    private int mDragCorner;
    private int touchSize;

    /**
     * 是否要裁剪,false:表示仅预览并确认
     */
    private boolean isCropView;
    /**
     * 白内障功能
     */
    private boolean isCataract;
    private final Paint eraserPaint;
    private RectF rectF;
    private final float maskCorner;
    private int cataractColor;

    public MagicCropView(Context context) {
        this(context, null);
    }

    public MagicCropView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MagicCropView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        touchSize = getResources().getDimensionPixelOffset(R.dimen.crop_touch_size);
        mMatrix = new Matrix();
        mDragDrawable = ContextCompat.getDrawable(context, R.drawable.ic_drag);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setStrokeWidth(getResources().getDimension(R.dimen.crop_stroke_width));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(Color.WHITE);

        eraserPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        maskCorner = getResources().getDimension(R.dimen.mask_corner);
        cataractColor = ContextCompat.getColor(context, R.color.cataract_color);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        mMatrix.mapRect(new RectF(0, 0, w, h));
        if (mCropBounds != null && !mCropBounds.isEmpty()) {
            return;
        }
        setDefaultCropBounds();
        setDefaultCornerBounds();
    }

    private void setDefaultCropBounds() {
        int marginHor = getResources().getDimensionPixelOffset(R.dimen.mask_bg_margin_hor);
        int marginVer = getResources().getDimensionPixelOffset(R.dimen.mask_bg_margin_ver);
        mCropBounds = new Rect(marginHor, marginHor, getWidth() - marginHor, getHeight() - marginVer);
        rectF = new RectF(mCropBounds);
    }

    private void setDefaultCornerBounds() {
        createOrUpdateBounds(CORNER_LEFT_TOP);
        createOrUpdateBounds(CORNER_RIGHT_TOP);
        createOrUpdateBounds(CORNER_LEFT_BOTTOM);
        createOrUpdateBounds(CORNER_RIGHT_BOTTOM);
    }

    private void createOrUpdateBounds(int cornerType) {
        if (cornerType == CORNER_LEFT_TOP) {
            if (mBounds1 == null) {
                mBounds1 = new Rect();
            }
            mBounds1.set(mCropBounds.left - touchSize, mCropBounds.top - touchSize, mCropBounds.left + touchSize, mCropBounds.top + touchSize);
        } else if (cornerType == CORNER_RIGHT_TOP) {
            if (mBounds2 == null) {
                mBounds2 = new Rect();
            }
            mBounds2.set(mCropBounds.right - touchSize, mCropBounds.top - touchSize, mCropBounds.right + touchSize, mCropBounds.top + touchSize);
        } else if (cornerType == CORNER_LEFT_BOTTOM) {
            if (mBounds3 == null) {
                mBounds3 = new Rect();
            }
            mBounds3.set(mCropBounds.left - touchSize, mCropBounds.bottom - touchSize, mCropBounds.left + touchSize, mCropBounds.bottom + touchSize);
        } else if (cornerType == CORNER_RIGHT_BOTTOM) {
            if (mBounds4 == null) {
                mBounds4 = new Rect();
            }
            mBounds4.set(mCropBounds.right - touchSize, mCropBounds.bottom - touchSize, mCropBounds.right + touchSize, mCropBounds.bottom + touchSize);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.BLACK);

        if (mCropBitmap == null) {
            return;
        }
        Log.d("TAG", "onDraw宽高: " + mCropBitmap.getWidth() + "=====" + mCropBitmap.getHeight());
        canvas.drawBitmap(mCropBitmap, 0, 0, null);
        if (!isCropView) {
            //如果不需要裁剪，直接返回
            return;
        }
        if (isCataract) {
            canvas.drawColor(cataractColor);
            canvas.drawRect(rectF, eraserPaint);
        }
        canvas.drawRect(mCropBounds, mPaint);

        if (isDragView) {
            if (mDragCorner == CORNER_LEFT_TOP) {
                mDragDrawable.setBounds(mBounds1);
                mDragDrawable.draw(canvas);
            } else if (mDragCorner == CORNER_RIGHT_TOP) {
                mDragDrawable.setBounds(mBounds2);
                mDragDrawable.draw(canvas);
            } else if (mDragCorner == CORNER_LEFT_BOTTOM) {
                mDragDrawable.setBounds(mBounds3);
                mDragDrawable.draw(canvas);
            } else if (mDragCorner == CORNER_RIGHT_BOTTOM) {
                mDragDrawable.setBounds(mBounds4);
                mDragDrawable.draw(canvas);
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!dragCropEnable) {
            return super.onTouchEvent(event);
        }
        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        if (action == MotionEvent.ACTION_DOWN) {
            isDragView = false;
            if (mBounds1.contains(x, y)) {
                isDragView = true;
                mDragCorner = CORNER_LEFT_TOP;
            } else if (mBounds2.contains(x, y)) {
                isDragView = true;
                mDragCorner = CORNER_RIGHT_TOP;
            } else if (mBounds3.contains(x, y)) {
                isDragView = true;
                mDragCorner = CORNER_LEFT_BOTTOM;
            } else if (mBounds4.contains(x, y)) {
                isDragView = true;
                mDragCorner = CORNER_RIGHT_BOTTOM;
            }
        } else if (action == MotionEvent.ACTION_MOVE) {
            if (isDragView) {
                if (mDragCorner == CORNER_LEFT_TOP) {
                    mCropBounds.left = x;
                    mCropBounds.top = y;
                } else if (mDragCorner == CORNER_RIGHT_TOP) {
                    mCropBounds.right = x;
                    mCropBounds.top = y;
                } else if (mDragCorner == CORNER_LEFT_BOTTOM) {
                    mCropBounds.left = x;
                    mCropBounds.bottom = y;
                } else if (mDragCorner == CORNER_RIGHT_BOTTOM) {
                    mCropBounds.right = x;
                    mCropBounds.bottom = y;
                }
                rectF.set(mCropBounds);
                createOrUpdateBounds(CORNER_LEFT_TOP);
                createOrUpdateBounds(CORNER_RIGHT_TOP);
                createOrUpdateBounds(CORNER_LEFT_BOTTOM);
                createOrUpdateBounds(CORNER_RIGHT_BOTTOM);
                invalidate();
            }
            return true;
        }
        return true;
    }

    public void startCropBitmap(Bitmap bitmap) {
        this.mCropBitmap = bitmap;
        requestLayout();
    }

    public void startCropBitmap(String filePath, int width, int height) {
        mMatrix.reset();
        int rotation = FileUtils.getImageRotation(filePath);
        mMatrix.postRotate(rotation);

        //采样缩放decode图片文件
        Bitmap bitmap = BitmapUtils.adjustSize(filePath, width, height);
        //旋转
        bitmap = BitmapUtils.rotationBitmap(bitmap, rotation);
        //缩放
        bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
        startCropBitmap(bitmap);
    }

    public void startCropBitmap(ByteArrayOutputStream stream, int rotation, int width, int height) {
        mMatrix.postRotate(rotation);
        byte[] bytes = stream.toByteArray();
        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        bitmap = BitmapUtils.rotationBitmap(bitmap, rotation);
        //缩放
        bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);
        startCropBitmap(bitmap);
    }

    public boolean cropToPicture(File cropFile) {
        //先裁剪，再保存
        Bitmap bitmap = mCropBitmap;
        if (isCropView) {
            bitmap = Bitmap.createBitmap(mCropBitmap, mCropBounds.left, mCropBounds.top, mCropBounds.width(), mCropBounds.height());
        }
        return BitmapUtils.saveBitmapToFile(bitmap, cropFile);
    }

    public void setIsCropView(boolean isCropView) {
        this.isCropView = isCropView;
    }

    public void setCropBounds(Rect cropBounds) {
        if (cropBounds == null || cropBounds.isEmpty()) {
            return;
        }
        Log.d("TAG", "setCropBounds: " + mCropBounds);
        Log.d("TAG", "setCropBounds: " + cropBounds);
        this.mCropBounds = cropBounds;
        rectF = new RectF(mCropBounds);
        setDefaultCornerBounds();
        invalidate();
    }

    /**
     * 是否要白内障
     */
    public void setCataract(boolean cataract) {
        isCataract = cataract;
        invalidate();
    }

    public void setCataractColor(int cataractColor) {
        if (cataractColor == 0) {
            return;
        }
        this.cataractColor = cataractColor;
        invalidate();
    }

    public void setDragCropEnable(boolean dragCropEnable) {
        this.dragCropEnable = dragCropEnable;
    }
}
